﻿/*!
* easyValidate JavaScript Library v1.5
* http://code.google.com/p/ornamentframework
*
* Copyright 2010
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://code.google.com/p/ornamentframework/wiki/LICENSE
*
* Date: 2010-6-17
*/
(function($) {

    /* disabled or enabled 
    $.easyValidate(true,"groupName1","groupName2"); ||$.easyValidate(true)
    $.easyValidate(true,$("target"));        
    */

    //$.easyValidate('check',"groupName1","groupName2");|| $.easyValidate('check');
    //$.easyValidate('check',$("#targetid")) || $.easyValidate('check','groupName',$("#targetid")....);


    $.easyValidate = function(option) {
        if (typeof option == 'object') {
            $.extend($.easyValidate.option, option);
            return;
        }
        var isEnable = typeof option == 'boolean';
        var fun = isEnable ? methods['enable'] : methods[option]
        var argument = isEnable ? arguments : [].slice.call(arguments, 1);
        return fun.apply(methods, argument);
    }

    $.easyValidate.option = {
        onError: function(messages) { alert(messages.join("\r\n")); },
        onCorrect: false,
        onFocus: false,
        focus: true,
        validateDisabled: false, //check disabled text?
        summary: function(aryTargets, aryMessages) {// if set to false, it will stop Validate another control and disposed message
            alert(aryMessages.join("\r\n"));
        }
    };

    var methods = {
        checkTarget: function(target, aryError) {
            if (target.data("eyVlid").enabled == false || target.attr("disabled") == "disabled")
                return true;
            var events = target.data("eyVlid").events;
            var allCorrect = true;
            for (var eventName in events) {
                var errorMessage = check.apply(target, [eventName]);
                if (errorMessage.length != 0) {
                    aryError.push({ message: errorMessage, target: target });
                    allCorrect = false;
                }
            }
            if (allCorrect) {
                doCorrect(target);
                return true;
            }
            return false;
        },
        check: function() {//args is groupName1,groupName2 ....
            var validateTargetGroup = getTargetSetByGroup(arguments);
            var result = [];
            for (var key in validateTargetGroup) {
                $(validateTargetGroup[key]).each(function() {
                    if (!methods.checkTarget($(this), result) && $.easyValidate.option.summary === false) {
                        return false;
                    }
                });
            }

            var aryMessage = [], aryTarget = [];
            var sumarry = $.isFunction($.easyValidate.option.summary);
            $(result).each(function() {
                if (sumarry) {
                    aryMessage.push(this.message.join("\r\n"));
                    aryTarget.push(this.target);
                }
                else {
                    showError(this.target, this.message);
                }
            });
            if (sumarry && aryTarget.length != 0) {
                $.easyValidate.option.summary(aryTarget, aryMessage);
            }
            return result.length === 0;
        },

        enable: function(enabled) {
            var validateTargetGroup = getTargetSetByGroup([].slice.call(arguments, 1));
            for (var key in validateTargetGroup) {
                $(validateTargetGroup[key]).each(function() {
                    $(this).data("eyVlid").enabled = enabled;
                });
            }
        }

    }

    $(document).data("groups", {
        groups: {
            defaults: []//save the object of html target. the json key (property) is the Group Name,
        }
    });

    var getTargetSetByGroup = function(aryGroupNamesOrTargets) {
        var result;
        if (aryGroupNamesOrTargets.length !== 0) {
            result = { 'tG': [] };
            for (var i = 0; i < aryGroupNamesOrTargets.length; i++) {
                var val = aryGroupNamesOrTargets[i];
                if (typeof (val) == 'string') {
                    var group = $(document).data("groups").groups[val];
                    if (group != undefined) {
                        result[val] = group;
                    }
                }
                else {
                    result['tG'].push(val);
                }
            }
        }
        else {
            result = $(document).data("groups").groups;
        }
        return result;
    }

    var init = function(target, defaultOpts, op) {
        target = $(target);
        if (target.length == 0) {
            return target;
        }

        var opts = $.extend({}, $.fn.vCustom.defaults, defaultOpts, op);

        var targetOpts = target.data("eyVlid");
        if (!targetOpts) {
            targetOpts = {
                events: {}, //key is event name, value is opts.
                enabled: true,
                group: opts.group,
                onCorrect: opts.onCorrect,
                onError: opts.onError
            };
            target.data("eyVlid", targetOpts);
        }

        var eventName = opts.event;
        var registedEvent = targetOpts.events[eventName] !== undefined;
        if (!registedEvent) {
            targetOpts.events[eventName] = [];
        }
        targetOpts.events[eventName].push(opts);
        opts = undefined;
        var globalGroups = $(document).data("groups").groups
        if (globalGroups[targetOpts.group] == undefined)
            globalGroups[targetOpts.group] = [];

        target.each(function() {
            if ($.inArray(this, globalGroups[targetOpts.group]) == -1) {
                globalGroups[targetOpts.group].push(this);
            }
        });

        if (!registedEvent && eventName != false) {
            target.bind(eventName, function(e) {
                var errorMessage = check.apply(target, [eventName]);
                if (errorMessage.length == 0) {
                    return doCorrect(target);
                }
                else {
                    return showError(target, errorMessage);
                }
            });
        }

        return target;
    };


    var check = function(event) {
        var target = this;
        var message = [];
        var targetOpts = target.data("eyVlid");

        if (!targetOpts.enabled) {
            return message;
        }

        $(targetOpts.events[event]).each(function() {
			var v=target.val();
            if ((v==null|| v=="") && this.empty !== true) {
                return true;
            }
            if (!this.check.call(target, this)) {
                message.push(this.errorText);
                if (this.errorBreak)
                    return false;
            }
        });

        return message;
    };

    var doCorrect = function(target) {
        var opts = target.data("eyVlid");
        var correctFunction = $.isFunction(opts.onCorrectFunction) ?
            opts.onCorrect : $.easyValidate.option.onCorrect;
        if ($.isFunction(correctFunction)) {
            correctFunction.call(target, opts);
        }
    };

    var showError = function(target, errorText) {
        var opts = target.data("eyVlid");
        var onErrorFunction = $.isFunction(opts.onError) ?
            opts.onError : $.easyValidate.option.onError;
        return onErrorFunction.call(target, errorText, opts);
    };

    $.fn.vCustom = function(op, customerFunction) {
        if (customerFunction != undefined) {
            op.check = customerFunction;
        }
        init(this, $.fn.vCustom.defaults, op);
    };

    $.fn.vCustom.defaults = {
        //following only the first Validator has effect,another validator will use the first Validator. 
        group: "defaults", //group of this target.
        enabled: true, //enabled or disabled target's validators.
        onError: false, // function(opt); this poiner is target;
        onCorrect: false, // function(opt); this poiner is target;
        paramers: null, //this value will be pass to onError or onCorrect,
        correctText: "信息正确", //following setting for each validator.
        errorText: "验证失败",
        event: "blur",
        empty: false,
        errorBreak: true, //don't use next validate to check value, if this has errro.
        check: function(opts, pam) { alert("请填写customFunction"); }
    };

    $.fn.vRequire = function(op) {
        return init(this, $.fn.vRequire.defaults, op);
    };

    $.fn.vRequire.defaults = {
        errorText: "输入有效值",
        empty: true,
        trim: true,
        check: function(op) {
			var v=this.val();
			if(v==null)
				return false;
            var a = op.trim ? $.trim(v) : v;
            return /\w+/.test(a);
        }
    }

    $.fn.vLength = function(op) {
        $(this).attr("maxlength", op.max);
        return init(this, $.fn.vLength.defaults, op);
    };

    $.fn.vLength.defaults = $.extend({}, $.fn.vCustom.defaults, {
        min: 0,
        max: 9999,
        errorText: "长度要做{min}和{max}之间",
        check: function(opts) {
            var length = this.val().length;
            var message = opts.errorText;
            if (message.indexOf("{min}") != -1 || message.indexOf("{max}") != -1) {
                opts.errorText = message.replace("{min}", opts.min).replace("{max}", opts.max);
            }
            return length <= opts.max && length >= opts.min;
        }
    });


    $.fn.vCompare = function(op) {
        return init(this, $.fn.vCompare.defaults, op);
    };

    $.fn.vCompare.defaults =
     {
         empty: true,
         target: false,
         errorText: "不匹配",
         operator: "==", //接受 <= >= < >等操作符
         check: function() {
             var a = arguments;
             var v = $.isFunction(a[0].target) ? a[0].target.call(this) : a[0].target.val();
             return eval("this.val()" + a[0].operator + "v");
         }
     }

    $.fn.vRegex = function(op) {
        return init(this, $.fn.vRegex.defaults, op);
    };

    $.fn.vRegex.defaults = {
        pattern: /.*/,
        errorText: "输入信息不正确",
        check: function(opts) {
            return opts.pattern.test(this.val());
        }
    }


    $.fn.vAjax = function(op) {
        return init(this, $.fn.vAjax.defaults, op);
    };

    $.fn.vAjax.defaults = {
        dataType: 'JSON',
        errorText: "输入信息不正确",
        onEndRequest: false, //请求成功后的，要做的处理        
        check: function(opts) {
            var curVal = opts.data();
            if (curVal !== false) {
                var preVal = $(this).data("preVal");
                var sendAjax = preVal == undefined;
                if (!sendAjax) {
                    for (var key in curVal) {
                        if (curVal[key] != preVal[key]) {
                            sendAjax = true;
                        }
                    }
                }
                $(this).data("preVal", curVal);
            }
            if (sendAjax) {
                var result = $.ajax({
                    url: opts.url,
                    dataType: opts.dataType,
                    data: curVal,
                    asyn: false
                });
                if ($.isFunction(opts.onEndRequest)) {
                    $(this).data("checkResult", opts.onEndRequest(this, result));
                }
            }
            return $(this).data("checkResult");
        }
    }

    //---------------一下是常用扩展--------------------
    $.fn.vNumber = function(op) {
        $(this).attr("maxlength", op.max.length);
        return init(this, $.fn.vRang.defaults, op);
    };

    $.fn.vNumber.defaults = {
        errorText: "请输入范围在{min}和{max}之间的数字",
        check: function(opts) {
            var a = new RegExp("^\d{" + opts.min.toString().length + "," + opts.max.toString().length + "}$");
            opts.errorText = opts.errorText.replace("{min}", opts.min).replace("{max}", opts.max);
            var result = a.test(this.val());
            if (result) {
                var inte = parseFloat(this.val())
                return inte >= opts.min && inte <= opts.max;
            }
            return false;
        }
    }

    $.fn.vEmail = function(op) {
        return init(this,
        $.fn.vRegex.defaults,
            { pattern: /^([A-Za-z0-9_\.-]+)@([\da-zA-Z\.-]+)\.([a-zA-Z\.]{2,6})$/,
                errorText: "邮件格式不正确"
            }, op
        );
    }
})($);